package com.onlyxiahui.extend.action.spring.boot.config;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.onlyxiahui.extend.action.spring.boot.properties.OnlyActionDispatcherProperties;
import com.onlyxiahui.framework.action.dispatcher.config.ActionConfigurer;
import com.onlyxiahui.framework.action.dispatcher.extend.ResultHandler;
import com.onlyxiahui.framework.action.dispatcher.general.GeneralMessageHandler;
import com.onlyxiahui.framework.action.dispatcher.general.config.GeneralActionDispatcher;
import com.onlyxiahui.framework.action.dispatcher.general.extend.ActionMessageResolver;
import com.onlyxiahui.framework.action.dispatcher.general.extend.impl.GeneralActionBox;
import com.onlyxiahui.framework.action.dispatcher.general.handler.GeneralResultHandler;
import com.onlyxiahui.framework.action.dispatcher.general.util.ActionDispatcherJsonUtil;
import com.onlyxiahui.framework.json.validator.error.ErrorInfoEnum;

/**
 * <br>
 * Date 2019-12-03 17:32:35<br>
 * 
 * @author XiaHui [onlovexiahui@qq.com]<br>
 * @since 1.0.0
 */
@EnableConfigurationProperties(OnlyActionDispatcherProperties.class)
public class OnlyDispatcherConfig {

	@Autowired()
	private OnlyActionDispatcherProperties onlyActionDispatcherProperties;

	@Autowired(required = false)
	private List<ActionConfigurer> configurers;

	@Autowired(required = false)
	private ActionMessageResolver actionMessageResolver;

	@PostConstruct
	public void config() {
		String errorCodePrefix = onlyActionDispatcherProperties.getValidateErrorCodePrefix();
		String errorCodeSeparator = onlyActionDispatcherProperties.getValidateErrorCodeSeparator();
		ErrorInfoEnum.setType(null == errorCodePrefix ? "" : errorCodePrefix, null == errorCodeSeparator ? "" : errorCodeSeparator);
	}

	@Bean
	public GeneralActionDispatcher generalActionDispatcher() {

		Set<String> actionPackages = onlyActionDispatcherProperties.getActionPackages();
//		String pathSeparator = onlyActionDispatcherProperties.getPathSeparator();
		Set<String> validatorPaths = onlyActionDispatcherProperties.getValidatorPaths();
		String validateProperty = onlyActionDispatcherProperties.getValidateRootProperty();

		if (null == validatorPaths) {
			validatorPaths = new HashSet<>();
		}

		if (validatorPaths.isEmpty()) {
			validatorPaths.add("classpath*:/validator/**/*.json");
		}

		String all = "*";
		String actionValidateProperty = null;
		if (!StringUtils.isEmpty(validateProperty)) {
			if (all.equals(validateProperty)) {
				actionValidateProperty = null;
			} else {
				actionValidateProperty = validateProperty;
			}
		}

		GeneralActionBox ab = generalActionBox();

		GeneralActionDispatcher bean = new GeneralActionDispatcher();

		bean.add(ab);
		if (!CollectionUtils.isEmpty(configurers) && null != bean) {
			for (ActionConfigurer c : configurers) {
				bean.addConfig(c);
			}
		}

//		if (!StringUtils.isEmpty(pathSeparator)) {
//			bean.getActionRegistry().setSeparator(pathSeparator);
//		}

		for (String validatorPath : validatorPaths) {
			bean.addActionValidator(validatorPath);
		}

		bean.setActionValidateRootProperty(actionValidateProperty);

		if (null != actionPackages && !actionPackages.isEmpty()) {
			for (String path : actionPackages) {
				bean.scan(path);
			}
		}
		return bean;
	}

	@Bean
	public GeneralMessageHandler generalMessageHandler() {
		GeneralActionDispatcher actionDispatcher = generalActionDispatcher();

		GeneralMessageHandler bean = new GeneralMessageHandler(null);

		bean.setActionDispatcher(actionDispatcher);
		bean.setActionMessageResolver(actionMessageResolver);
		return bean;
	}

	@Bean
	public GeneralActionBox generalActionBox() {
		GeneralActionBox bean = new GeneralActionBox();
		return bean;
	}

	@Autowired(required = false)
	@Bean
	@ConditionalOnProperty(prefix = "only.action.dispatcher", name = "response-handle-enable", matchIfMissing = true)
	public GeneralResultHandler generalResultHandler(List<ResultHandler> handlers) {

		GeneralResultHandler bean = new GeneralResultHandler(handlers);
		Set<String> responseHandleExcludePaths = onlyActionDispatcherProperties.getResponseHandleExcludePaths();
		if (null != responseHandleExcludePaths) {
			for (String pathExclude : responseHandleExcludePaths) {

				if (!StringUtils.isEmpty(pathExclude)) {
					// exclude=[{"path":"/actuator"},{"path":"/actuator/*"}]
					if (ActionDispatcherJsonUtil.maybeJsonArray(pathExclude)) {
						JSONArray ja = JSONArray.parseArray(pathExclude);

						if (null != ja && !ja.isEmpty()) {
							int size = ja.size();
							for (int i = 0; i < size; i++) {
								JSONObject o = ja.getJSONObject(i);
								String path = (o).getString("path");
								if (!StringUtils.isEmpty(path)) {
									bean.addExcludePath(path);
								}
							}
						}
					} else {
						bean.addExcludePath(pathExclude);
					}
				}
			}
		}
		boolean responseHandleEnable = onlyActionDispatcherProperties.isResponseHandleEnable();
		if (responseHandleEnable) {
			GeneralActionDispatcher actionDispatcher = generalActionDispatcher();
			actionDispatcher.getResultHandlerRegistry().add(bean);
		}
		return bean;
	}
}
